package com.yf.esms.service;

import com.alibaba.fastjson.JSON;
import com.yf.esms.model.entries.GoodsInfo;
import com.yf.esms.model.entries.GoodsInfoSearchResult;
import com.yf.esms.model.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author 99698
 */
@Service
@Slf4j
public class GoodsService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 新增商品索引
     * @param indexName 索引名
     * @return
     * @throws IOException
     */
    public Boolean createIndex(String indexName) throws IOException {

        CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        return createIndexResponse.isAcknowledged();
    }

    /**
     * 向商品索引中新增一条商品信息
     * @param goodsInsertOneVo
     * @return
     * @throws IOException
     */
    public String insertOne(GoodsInsertOneVo goodsInsertOneVo) throws IOException {
        IndexRequest indexRequest = new IndexRequest();
        indexRequest
                //指定索引
                .index(goodsInsertOneVo.getIndexName())
                //json字符串类型的数据
                .source(JSON.toJSONString(goodsInsertOneVo.getGoodsInfo()), XContentType.JSON);
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        return indexResponse.getId();
    }


    /**
     * 批量插入商品
     * @param goodsInsertBatchVo
     * @return
     * @throws IOException
     */
    public List<String> insertBatch(GoodsInsertBatchVo goodsInsertBatchVo) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        for (GoodsInfo goodsInfo : goodsInsertBatchVo.getGoodsInfos()) {
            IndexRequest indexRequest = new IndexRequest();
            indexRequest.index(goodsInsertBatchVo.getIndexName()).source(JSON.toJSONString(goodsInfo),XContentType.JSON);
            bulkRequest.add(indexRequest);
        }
        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        BulkItemResponse[] items = bulk.getItems();
        List<String> list = new ArrayList<>();
        for (BulkItemResponse bulkItemResponse : items) {
            String id = bulkItemResponse.getResponse().getId();
            list.add(id);
        }
        return list;
    }

    public SearchGoodsVo all(String indexName) throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(indexName);

        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.matchAllQuery()).size(10000);
        searchRequest.source(builder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        long totalNum = searchResponse.getHits().getTotalHits().value;
        SearchHit[] hits = searchResponse.getHits().getHits();
        List<GoodsInfoSearchResult> goodsInfoSearchResults = new ArrayList<>();
        for (SearchHit hit : hits) {
            String id = hit.getId();
            String sourceAsString = hit.getSourceAsString();
            GoodsInfo goodsInfo = JSON.parseObject(sourceAsString, GoodsInfo.class);
            GoodsInfoSearchResult goodsInfoSearchResult = new GoodsInfoSearchResult();
            BeanUtils.copyProperties(goodsInfo,goodsInfoSearchResult);
            goodsInfoSearchResult.setId(id);
            goodsInfoSearchResults.add(goodsInfoSearchResult);
        }
        SearchGoodsVo searchGoodsVo = new SearchGoodsVo();
        searchGoodsVo.setTotalNum(totalNum);
        searchGoodsVo.setGoodsInfoSearchResults(goodsInfoSearchResults);
        return searchGoodsVo;
    }

    public SearchGoodsVo searchByKeyword(GoodsSearchByKeywordVo goodsSearchByKeywordVo) throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(goodsSearchByKeywordVo.getIndexName());
        SearchSourceBuilder builder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("commonName", goodsSearchByKeywordVo.getKeyword());

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.requireFieldMatch(true);
        highlightBuilder.field("commonName");
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        builder.highlighter(highlightBuilder);

        builder.query(matchQueryBuilder)
                .from(goodsSearchByKeywordVo.getPageSize()*(goodsSearchByKeywordVo.getCurrentPage()-1))
                .size(goodsSearchByKeywordVo.getPageSize());
        searchRequest.source(builder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
        long value = searchResponse.getHits().getTotalHits().value;
        SearchHit[] hits = searchResponse.getHits().getHits();
        List<GoodsInfoSearchResult> goodsInfoSearchResults = new ArrayList<>();
        for (SearchHit searchHit : hits) {
            String id = searchHit.getId();

            Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
            HighlightField highlightCommonName = highlightFields.get("commonName");
            String newCommonName = "";
            if (null != highlightCommonName){
                Text[] fragments = highlightCommonName.getFragments();
                for (Text text : fragments) {
                    newCommonName += text;
                }
            }
            String sourceAsString = searchHit.getSourceAsString();
            GoodsInfo goodsInfo = JSON.parseObject(sourceAsString, GoodsInfo.class);
            goodsInfo.setCommonName(newCommonName);
            GoodsInfoSearchResult goodsInfoSearchResult = new GoodsInfoSearchResult();
            BeanUtils.copyProperties(goodsInfo,goodsInfoSearchResult);
            goodsInfoSearchResult.setId(id);
            goodsInfoSearchResults.add(goodsInfoSearchResult);
        }
        SearchGoodsVo searchGoodsVo = new SearchGoodsVo();
        searchGoodsVo.setGoodsInfoSearchResults(goodsInfoSearchResults);
        searchGoodsVo.setTotalNum(value);
        return searchGoodsVo;
    }

    public SearchGoodsVo selectByCatId(GoodsSearchByCatIdVo goodsSearchByCatIdVo) throws IOException {

        List<Integer> catIds = Arrays.asList(1006081655, 1006081914, 1006081914);
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(goodsSearchByCatIdVo.getIndexName());
        SearchSourceBuilder builder = new SearchSourceBuilder();

        BoolQueryBuilder boolShouldQueryBuilder = QueryBuilders.boolQuery();
        for (Integer catId : catIds) {
            MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("catId", catId);
            boolShouldQueryBuilder.should(matchQueryBuilder);
        }
        builder.query(boolShouldQueryBuilder).from(goodsSearchByCatIdVo.getPageSize() * (goodsSearchByCatIdVo.getCurrentPage() - 1)).size(goodsSearchByCatIdVo.getPageSize());
        searchRequest.source(builder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        long value = searchResponse.getHits().getTotalHits().value;
        SearchHit[] hits = searchResponse.getHits().getHits();
        List<GoodsInfoSearchResult> goodsInfoSearchResults = new ArrayList<>();
        for (SearchHit searchHit : hits) {
            String id = searchHit.getId();
            String sourceAsString = searchHit.getSourceAsString();
            GoodsInfo goodsInfo = JSON.parseObject(sourceAsString, GoodsInfo.class);
            GoodsInfoSearchResult goodsInfoSearchResult = new GoodsInfoSearchResult();
            BeanUtils.copyProperties(goodsInfo,goodsInfoSearchResult);
            goodsInfoSearchResult.setId(id);
            goodsInfoSearchResults.add(goodsInfoSearchResult);
        }

        SearchGoodsVo searchGoodsVo = new SearchGoodsVo();
        searchGoodsVo.setGoodsInfoSearchResults(goodsInfoSearchResults);
        searchGoodsVo.setTotalNum(value);
        return searchGoodsVo;
    }
}
